package com.voodoo.lib_utils;

import java.nio.charset.StandardCharsets;

/**
 * Author: voodoo
 * CreateDate: 2020-03-26 026 下午 02:34
 * Description: Byte字节工具类
 * <p>String str2Hex(String str) 字符串转化成为Hex字符串</p>
 * <p>String hexToString(String hexStr) Hex转换成为可打印的字符串</p>
 * <p>byte[] hexToByteArr(String inHex) Hex转byte数组</p>
 * <p>String byteArrToHex(byte[] bytes, int size) 将byte数组转换成Hex字符串</p>
 * <p>String byteArrToHex(byte[] bytes) 将byte数组转换为Hex字符串</p>
 * <p>String byteToHex(Byte inByte) 单个byte转Hex的字符</p>
 * <p>String getCRC_16(byte[] bytes) 计算CRC16校验码，逐个求和</p>
 * <p>String getSum16(byte[] msg, int length) 指令校验和,并取出后两位字节</p>
 */
public class ByteUtils {

    /**
     * 字符串转化成为Hex字符串
     */
    public static String str2Hex(String str) {
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < str.length(); i++) {
            int ch = (int) str.charAt(i);
            stringBuffer.append(Integer.toHexString(ch));
        }
        return stringBuffer.toString();
    }

    /**
     * Hex转换成为可打印的字符串
     */
    public static String hexToString(String hexStr) {
        if (hexStr == null || hexStr.equals("")) {
            return null;
        }
        hexStr = hexStr.replace(" ", "");
        byte[] baKeyword = new byte[hexStr.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            hexStr = new String(baKeyword, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hexStr;
    }

    /**
     * Hex转byte数组
     *
     * @param hex Hex字符串
     * @return byte[]
     */
    public static byte[] hexToByteArr(String hex) {
        int hexlen = hex.length();
        byte[] result;
        if ((hexlen & 0x1) == 1) { // 奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            hex = "0" + hex;
        } else {  // 偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
            j++;
        }
        return result;
    }

    /**
     * 将byte数组转换成Hex字符串
     *
     * @param bytes 要转换的byte数组
     * @param size  要转换的长度
     * @return 转换后的字符串（转大写之后的）
     */
    public static String byteArrToHex(byte[] bytes, int size) {
        StringBuilder stringBuilder = new StringBuilder();
        if (bytes == null || bytes.length <= 0 || bytes.length < size) {
            return null;
        }
        for (int i = 0; i < size; i++) {
            String hexString = Integer.toHexString(bytes[i] & 0xFF);
            if (hexString.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hexString);
            stringBuilder.append(" ");
        }
        return stringBuilder.toString().toUpperCase().trim();
    }

    /**
     * 将byte数组转换为Hex字符串
     *
     * @param bytes Byte数组
     * @return Hex格式的字符串
     */
    public static String byteArrToHex(byte[] bytes) {
        return byteArrToHex(bytes, bytes.length);
    }

    /**
     * 单个byte转Hex的字符
     *
     * @param inByte 字节
     * @return String 两位字符，byte<16 的话会添加上0，凑齐两位
     */
    public static String byteToHex(Byte inByte) {
        byte[] bytes = {inByte};
        return byteArrToHex(bytes);
    }

    /**
     * 计算CRC16校验码，逐个求和
     *
     * @param bytes 字节数组
     * @return {@link String} 校验码
     */
    public static String getCRC_16(byte[] bytes) {
        int CRC = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;
        int i, j;
        for (i = 0; i < bytes.length; i++) {
            CRC ^= ((int) bytes[i] & 0x000000ff);
            for (j = 0; j < 8; j++) {
                if ((CRC & 0x00000001) != 0) {
                    CRC >>= 1;
                    CRC ^= POLYNOMIAL;
                } else {
                    CRC >>= 1;
                }
            }
        }
        if (Integer.toHexString(CRC).toUpperCase().length() == 2) {
            return byteArrToHex(bytes) + "00" + Integer.toHexString(CRC).toUpperCase();
        } else if (Integer.toHexString(CRC).toUpperCase().length() == 3) {
            return byteArrToHex(bytes) + "0" + Integer.toHexString(CRC).toUpperCase();
        }
        return byteArrToHex(bytes) + Integer.toHexString(CRC).toUpperCase();
    }

    /**
     * 指令校验和,并取出后两位字节
     */
    public static String getSum16(byte[] msg, int length) {
        long mSum = 0;
        byte[] mByte = new byte[length];

        // 逐Byte添加位数和
        for (byte byteMsg : msg) {
            long mNum = ((long) byteMsg >= 0) ? (long) byteMsg : ((long) byteMsg + 256);
            mSum += mNum;
        }

        // 位数和转化为Byte数组
        for (int liv_Count = 0; liv_Count < length; liv_Count++) {
            mByte[length - liv_Count - 1] = (byte) (mSum >> (liv_Count * 8) & 0xff);
        }

        return byteArrToHex(msg, length) + byteArrToHex(mByte).substring(byteArrToHex(mByte).length() - 4);
    }


    /**
     * ascii2Str ascii转字符串
     * @param data 16进制的字符串数组
     * @return
     */
    public static String ascii2Str(String[] data) {
        StringBuffer stringBuffer = new StringBuffer();
        int[] decs = new int[data.length];
        for (int i = 0; i < data.length; i++) {
            decs[i] = Integer.parseInt(data[i], 16);
        }
        for (int decAscii : decs) {
            stringBuffer.append((char) decAscii);
        }
        return stringBuffer.toString();
    }
}